import time


# 自定义枚举类
class CustomEncodeEnum:
    # 创建内部成员枚举字典
    _members: dict = {
        'ZERO': (0, 'Ψ'),
        'ONE': (1, '1'),
        'TWO': (2, '2'),
        'THREE': (3, '3'),
        'FOUR': (4, '4'),
        'FIVE': (5, '5'),
        'SIX': (6, '6'),
        'SEVEN': (7, '7'),
        'EIGHT': (8, '8'),
        'NINE': (9, '9'),
        'TEN': (10, 'a'),
        'ELEVEN': (11, 'b'),
        'TWELVE': (12, 'C'),
        'THIRTEEN': (13, 'd'),
        'FOURTEEN': (14, 'e'),
        'FIFTEEN': (15, 'f'),
        'SIXTEEN': (16, 'g'),
        'SEVENTEEN': (17, 'h'),
        'EIGHTEEN': (18, 'Δ'),
        'NINETEEN': (19, 'j'),
        'TWENTY': (20, 'k'),
        'TWENTY_ONE': (21, '∧'),
        'TWENTY_TWO': (22, "m"),
        'TWENTY_THREE': (23, "n"),
        'TWENTY_FOUR': (24, "∑"),
        'TWENTY_FIVE': (25, "p"),
        'TWENTY_SIX': (26, "q"),
        'TWENTY_SEVEN': (27, "r"),
        'TWENTY_EIGHT': (28, "s"),
        'TWENTY_NINE': (29, "t"),
        'THIRTY': (30, "u"),
        'THIRTY_ONE': (31, "v"),
        'THIRTY_TWO': (32, "w"),
        'THIRTY_THREE': (33, "x"),
        'THIRTY_FOUR': (34, "y"),
        'THIRTY_FIVE': (35, "z"),
        'THIRTY_SIX': (36, "A"),
        'THIRTY_SEVEN': (37, "B"),
        'THIRTY_EIGHT': (38, "C"),
        'THIRTY_NINE': (39, "D"),
        'FORTY': (40, "E"),
        'FORTY_ONE': (41, "F"),
        'FORTY_TWO': (42, "G"),
        'FORTY_THREE': (43, "H"),
        'FORTY_FOUR': (44, "I"),
        'FORTY_FIVE': (45, "J"),
        'FORTY_SIX': (46, "K"),
        'FORTY_SEVEN': (47, "L"),
        'FORTY_EIGHT': (48, "M"),
        'FORTY_NINE': (49, "N"),
        'FIFTY': (50, "O"),
        'FIFTY_ONE': (51, "P"),
        'FIFTY_TWO': (52, "Q"),
        'FIFTY_THREE': (53, "R"),
        'FIFTY_FOUR': (54, "S"),
        'FIFTY_FIVE': (55, "T"),
        'FIFTY_SIX': (56, "U"),
        'FIFTY_SEVEN': (57, "V"),
        'FIFTY_EIGHT': (58, "W"),
        'FIFTY_NINE': (59, "X"),
        'SIXTY': (60, "Y"),
        'SIXTY_ONE': (61, "Z"),
        'SIXTY_TWO': (62, "!"),
        'SIXTY_THREE': (63, "@"),
        'SIXTY_FOUR': (64, "#"),
        'SIXTY_FIVE': (65, "$"),
        'SIXTY_SIX': (66, "%"),
        'SIXTY_SEVEN': (67, "&"),
        'SIXTY_EIGHT': (68, "*"),
        'SIXTY_NINE': (69, "("),
        'SEVENTY': (70, ")"),
        'SEVENTY_ONE': (71, "["),
        'SEVENTY_TWO': (72, "]"),
        'SEVENTY_THREE': (73, "{"),
        'SEVENTY_FOUR': (74, "}"),
        'SEVENTY_FIVE': (75, "<"),
        'SEVENTY_SIX': (76, ">"),
        'SEVENTY_SEVEN': (77, "="),
        'SEVENTY_EIGHT': (78, "+"),
        'SEVENTY_NINE': (79, "π"),
        'EIGHTY': (80, "_"),
        'EIGHTY_ONE': (81, "|"),
        'EIGHTY_TWO': (82, "/"),
        'EIGHTY_THREE': (83, "~"),
        'EIGHTY_FOUR': (84, "£"),
        'EIGHTY_FIVE': (85, "?"),
        'EIGHTY_SIX': (86, ":"),
        'EIGHTY_SEVEN': (87, ";"),
        'EIGHTY_EIGHT': (88, ","),
        'EIGHTY_NINE': (89, "."),
        'NINETY': (90, "α"),
        'NINETY_ONE': (91, "β"),
        'NINETY_TWO': (92, "γ"),
        'NINETY_THREE': (93, "δ"),
        'NINETY_FOUR': (94, "ε"),
        'NINETY_FIVE': (95, "ζ"),
        'NINETY_SIX': (96, "Φ"),
        'NINETY_SEVEN': (97, "θ"),
        'NINETY_EIGHT': (98, "ι"),
        'NINETY_NINE': (99, "λ")
    }

    @staticmethod
    def get_value(code):
        # 根据code获取value
        for member, (c, v) in CustomEncodeEnum._members.items():
            if code == c:
                return v
        raise ValueError(f"Invalid code: {code}")

    @staticmethod
    def get_code(value):
        # 根据value获取code
        for member, (c, v) in CustomEncodeEnum._members.items():
            if value == v:
                return c
        raise ValueError(f"Invalid value: {value}")


# 序列号解密工具类
class SerialUtil:
    """
        ********************序列号加密区***********************
    """
    """
    1. 处理原始雪花ID：
        截取原始雪花ID的最后一位数字，用于后续计算表号。
        去掉最后一位数字，得到截短后的18位雪花ID。
    2. 计算表号并格式化：
        使用最后一位数字乘以1000，然后加上预设的表号（96），得到四位数的表号。
    3. 拼接雪花ID和表号：
        将截短后的雪花ID转换为字符串，并与格式化后的表号字符串拼接。
    4. 编码拼接后的字符串：
        遍历拼接后的字符串，每两个字符一组，通过CustomEncodeEnum.get_value方法（假设为简单映射到A-Z）进行编码，得到编码后的字符串。
    5. 处理当前时间戳：
        获取当前时间戳，并计算一个基于时间戳的偏移量（时间戳模11）。
    6. 对编码后的字符串进行偏移：
        根据时间戳偏移量，对编码后的字符串进行循环偏移，即将每个字符按偏移量移动到新位置，形成新的偏移编码字符串。
    7. 编码时间戳字符串：
        将当前时间戳转换为字符串，并每两个字符一组进行编码，得到编码后的时间戳字符串。
    8. 对编码后的时间戳字符串进行偏移：
    计算偏移编码字符串的哈希值，并使用哈希值对编码后的时间戳字符串长度取模，得到时间戳字符串的偏移量。
    9. 对编码后的时间戳字符串进行循环偏移，得到最终偏移的时间戳字符串。
        拼接最终字符串：
    10.遍历最终偏移的时间戳字符串，每次取一个字符，并与偏移编码字符串的前三个字符（如果剩余）进行拼接。
        如果拼接后的字符串超过3个字符，则只保留前三字符的偏移编码字符串，继续拼接后续的时间戳字符。
    11.格式化最终字符串：
        将最终拼接的字符串每4个字符插入一个-，形成最终序列号。
        如果最终序列号以-开头，则去除该-。
    12.输出结果：
        最终序列号 
    """

    @staticmethod
    def encode_serial_number(original_snowflake_id, table_number):
        # 截取最后一位
        last_digit = original_snowflake_id % 10
        # 截取后的18位雪花ID
        truncated_snowflake_id = original_snowflake_id // 10

        # 填充到四位
        formatted_table_number = (last_digit * 1000) + table_number

        # 拼接雪花ID和表号
        combined_str = str(truncated_snowflake_id) + str(formatted_table_number)

        # 通过映射表转换字符串
        encoded_str = ""
        for i in range(0, len(combined_str), 2):
            value = CustomEncodeEnum.get_value(int(combined_str[i:i + 2]))
            encoded_str += value

        # 获取当前时间戳
        current_timestamp = int(time.time())
        # 计算偏移量
        offset_for_encoded_str = current_timestamp % 11

        # 对编码后的字符串进行偏移
        offset_list = [0] * len(encoded_str)
        for i in range(len(encoded_str)):
            offset_index = (i + offset_for_encoded_str) % len(encoded_str)
            offset_list[offset_index] = encoded_str[i]
        offset_encoded_str = "".join(offset_list)

        # 时间戳字符串
        timestamp_str = str(current_timestamp)
        # 时间戳字符串通过映射表转换
        encoded_timestamp_str = ''
        for i in range(0, len(timestamp_str), 2):
            value = CustomEncodeEnum.get_value(int(timestamp_str[i:i + 2]))
            encoded_timestamp_str += value

        # 获取偏移字符串的hash值
        hash_value = abs(hash(offset_encoded_str))
        # 计算时间戳映射串的偏移量
        offset_for_timestamp_str = hash_value % len(encoded_timestamp_str)

        # 对时间戳映射串进行偏移
        offset_list = [0] * len(encoded_timestamp_str)
        for i in range(len(encoded_timestamp_str)):
            offset_index = (i + offset_for_timestamp_str) % len(encoded_timestamp_str)
            offset_list[offset_index] = encoded_timestamp_str[i]
        final_offset_timestamp_str = ''.join(offset_list)

        # 最终拼接字符串
        final_str = ''
        for i in range(len(final_offset_timestamp_str)):
            if len(offset_encoded_str) >= 3:
                temp_offset_encoded = offset_encoded_str[:3]
                offset_encoded_str = offset_encoded_str[3:]
            else:
                temp_offset_encoded = offset_encoded_str
            if i < 3:
                final_str += final_offset_timestamp_str[i] + temp_offset_encoded
            else:
                final_str += temp_offset_encoded + final_offset_timestamp_str[i:]
                break

        # 格式化最终字符串，每4位插入一个'-'
        final_serial = '-'.join(final_str[i:i + 4] for i in range(0, len(final_str), 4))
        if final_serial.startswith('-'):
            final_serial = final_serial[1:]  # 去除开头的'-'

        print("最终序列号:", final_serial)
        return final_serial

    """
        ********************序列号解码区***********************
    """

    """
    1. 分割和重组字符串：
        将最终序列号按-分割为多个部分。
        根据编码规则，重新组合时间戳偏移字符串和雪花ID+表号偏移字符串。
    2. 计算哈希值和偏移量：
        对雪花ID+表号偏移字符串计算哈希值，并据此获取时间戳字符串的偏移量。
        同样，使用时间戳解码后的值计算雪花ID+表号字符串的偏移量。
    3. 恢复偏移字符串：
        根据偏移量，恢复时间戳映射串和雪花ID+表号字符串的原始顺序。
    4. 映射回数字：
        使用CustomEncodeEnum.get_code方法将编码后的字符映射回数字，并重新组合成完整的字符串。
        将字符串转换为整数，并根据编码规则分离出雪花ID和表号。
    5. 返回结果：
        返回解码后的雪花ID和表号。
    """

    @staticmethod
    def decode_serial_number(final_serial):
        try:
            raw_str_list = final_serial.split('-')
            raw_time_offset_str = raw_str_list[0][0] + raw_str_list[1][0] + raw_str_list[2][0] + raw_str_list[3][-2:]
            raw_snow_table_no_offset_str = raw_str_list[0][1:] + raw_str_list[1][1:] + raw_str_list[2][1:] + raw_str_list[
                                                                                                                 3][:2]
            # 计算原始雪花id表号偏移字符串的hash值
            hash_value = abs(hash(raw_snow_table_no_offset_str))
            # 获取时间戳字符串的偏移值
            time_offset = hash_value % len(raw_time_offset_str)

            # 对时间戳映射串进行偏移回复
            offset_list = [0] * len(raw_time_offset_str)
            for i in range(len(raw_time_offset_str)):
                offset_index = ((i - time_offset) + len(raw_time_offset_str)) % len(raw_time_offset_str)
                offset_list[offset_index] = raw_time_offset_str[i]
            raw_time_reflect_str = ''.join(offset_list)
            # 映射回时间戳
            raw_time_str = ''
            for i in range(0, len(raw_time_reflect_str)):
                code = CustomEncodeEnum.get_code(raw_time_reflect_str[i])
                raw_time_str += str(code).zfill(2)
            # 获取时间戳
            decoded_timestamp = int(raw_time_str)
            # 计算雪花 + 表号字符串的偏移量
            offset_for_encoded_str = decoded_timestamp % 11
            # 回复偏移的雪花 + 表号字符串
            offset_list = [0] * len(raw_snow_table_no_offset_str)
            for i in range(len(raw_snow_table_no_offset_str)):
                offset_index = ((i - offset_for_encoded_str) + len(raw_snow_table_no_offset_str)) % len(
                    raw_snow_table_no_offset_str)
                offset_list[offset_index] = raw_snow_table_no_offset_str[i]
            raw_snow_table_no_reflect_str = ''.join(offset_list)
            # 映射回原始的数字
            raw_snow_table_no_str = ''
            for i in range(0, len(raw_snow_table_no_reflect_str)):
                code = CustomEncodeEnum.get_code(raw_snow_table_no_reflect_str[i])
                raw_snow_table_no_str += str(code).zfill(2)
            # 转数字
            raw_snow_table_no_int = int(raw_snow_table_no_str)
            # 获取表号
            table_no = raw_snow_table_no_int % 1000
            # 获取雪花id
            snow_flake = raw_snow_table_no_int // 1000
            if 0 <= table_no < 128 and str(snow_flake).startswith('1'):
                return snow_flake, table_no
            raise RuntimeError("serial_code_error")
        except Exception as e:
            print(e)
            return None, None
